




var Editor = (function () {
    "use strict";
    const Cu = Components.utils;
    function require(url) {
        let scope = {};
        Cu.import(url, scope);
        return scope;
    }
    let {MiscUtils} = require("chrome://jsm/content/utils.js");
    let {Prefs} = require("chrome://jsm/content/Preferences.js");
    let {Clipboard} = require("chrome://jsm/content/Clipboard.js");
    let {Dialogs} = require("chrome://jsm/content/Dialogs.js");
    let {FIO} = require("chrome://jsm/content/FileHelpers.js");
    let {OS} = require("resource://gre/modules/osfile.jsm");

    return {
        get editbox() {
            return document.getElementById("editbox");
        },

        get doc() {
            return this.editbox.contentDocument;
        },

        init(file_path, line) {
            var bypass = this.doc.getElementById("bypass");
            if (!bypass || !bypass.hasAttribute("inited")) {
                setTimeout(function () { Editor.init(file, line); }, 100);
                return;
            }

            bypass.setAttribute("lang", "en");
            bypass.setAttribute("syntax", file_path && /\.js$/.test(file_path) ?
                                "js" : "imacro");
            var evt = this.doc.createEvent("Events");
            evt.initEvent("iMacrosEditorInitEvent", true, false);
            bypass.dispatchEvent(evt);
            this.attachListeners();
            return file_path ? this.completeLoad(file_path, line) : 
                Promise.resolve();
        },

        attachListeners () {
            document.addEventListener("iMacrosEditorSaveEvent",
                                      function(e) { Editor.listen(e); },
                                      false);
            document.addEventListener("iMacrosEditorLoadEvent",
                                      function(e) { Editor.listen(e); },
                                      false);
        },

        saveFileAs() {
            let r = this.getEditAreaData();
            let dir = r.dirpath || Prefs.defaultMacroPath;
            var ext = r.syntax == "js" ? "js" : "iim";
            return Dialogs.browseForFileSave(
                "iMacros save file",
                r.filename || ("untitled."+ext), dir
            ).then( (file) => {
                return FIO.writeTextFile(file, r.content);
            });
        },


        getEditAreaData() {
            
            var bypass = this.doc.getElementById("bypass");
            var evt = this.doc.createEvent("Events");
            evt.initEvent("iMacrosEditorGetContentEvent", true, false);
            bypass.dispatchEvent(evt);
            var content = bypass.getAttribute("content");
            var filename = bypass.getAttribute("filename");
            var dirpath = bypass.getAttribute("dirpath");
            var syntax = bypass.getAttribute("syntax");

            return {content: content,
                    filename: filename,
                    dirpath: dirpath,
                    syntax: syntax};
        },

        saveFile() {
            let r = this.getEditAreaData();
            if (r.filename && r.dirpath) {
                let file_path = OS.Path.join(r.dirpath, r.filename);
                return FIO.writeTextFile(file_path, r.content);
            } else {
                return this.saveFileAs();
            }
        },


        checkFileChanged() {
            var r = this.getEditAreaData();
            if (r.filename && r.dirpath) {
                let file_path = OS.Path.join(r.dirpath, r.filename);
                return FIO.readTextFile(file_path).then(content => {
                    r.content = r.content.replace(/\r/g, "");
                    return content.replace(/\r/g, "") != r.content;
                });
            } else {
                return Promise.resolve(true);
            }
        },


        loadFile() {
            return Dialogs.browseForFileOpen("iMacros", Prefs.defaultMacroPath)
                .then(path => this.completeLoad(path));
        },

        
        completeLoad(path, line) {
            
            var bypass = this.doc.getElementById("bypass");
            bypass.setAttribute("filename", OS.Path.basename(path));
            bypass.setAttribute("dirpath", OS.Path.dirname(path));
            bypass.setAttribute("syntax", /\.js$/.test(path) ? "js" : "imacro");
            return FIO.readTextFile(path).then(content => {
                bypass.setAttribute("content", content);
                if (line) {             
                    
                    
                    let count = 1;
                    for(let i = 0; i < content.length; i++) {
                        if (count == line) {
                            bypass.setAttribute("start", i);
                            bypass.setAttribute("end", i);
                            break;
                        }
                        if (content[i] == "\r")
                            continue;
                        if (content[i] == "\n")
                            count++;
                    }
                }
                let evt = this.doc.createEvent("Events");
                evt.initEvent("iMacrosEditorLoadCompleteEvent", true, false);
                bypass.dispatchEvent(evt);
                
                document.title = OS.Path.basename(path)+" - iMacros Editor";
            });
        },


        getSelection() {
            
            var bypass = this.doc.getElementById("bypass");
            var evt = this.doc.createEvent("Events");
            evt.initEvent("iMacrosEditorGetSelection", true, false);
            bypass.dispatchEvent(evt);
            var selection = bypass.getAttribute("selection");
            return selection;
        },


        setSelection(text) {
            
            var bypass = this.doc.getElementById("bypass");
            var evt = this.doc.createEvent("Events");
            evt.initEvent("iMacrosEditorSetSelection", true, false);
            bypass.setAttribute("selection", text);
            bypass.dispatchEvent(evt);
        },
        
        

        onContextShowing() {
            var cut = document.getElementById("context-cut");
            var copy = document.getElementById("context-copy");
            var paste = document.getElementById("context-paste");
            var sel = this.getSelection();
            var clip_content = Clipboard.getString();
            if (sel && sel.length) {
                cut.disabled = false;
                copy.disabled = false;
                paste.disabled = true;
            } else {
                cut.disabled = true;
                copy.disabled = true;
                if (clip_content.length)
                    paste.disabled = false;
            }
        },


        cut() {
            let sel = this.getSelection();
            if (sel && sel.length) {
                Clipboard.putString(sel);
                this.setSelection("");
            }
        },


        copy() {
            let sel = this.getSelection();
            if (sel && sel.length) {
                Clipboard.putString(sel);
            }
        },


        paste() {
            let clip_content = Clipboard.getString();
            if (clip_content && clip_content.length) {
                this.setSelection(clip_content);
            }
        },


        listen(evt) {
            if (evt.type == "iMacrosEditorSaveEvent") {
                var content = evt.target.getAttribute("content");
                this.saveFileAs(evt).catch(Cu.reportError);
            } else if (evt.type == "iMacrosEditorLoadEvent") {
                this.loadFile(evt).catch(Cu.reportError);
            }
        },

        saveAndQuit() {
            Editor.saveFile().then(() => window.close())
                .catch(Cu.reportError);
        },

        cancel() {
            Editor.checkFileChanged().then(changed => {
                const msg = "File content was changed. Would you like to save changes?";
                return changed? Dialogs.confirm(msg)
                    .then(yes => yes && Editor.saveFile()) : 
                    Promise.resolve();
            }).then(() => window.close()).catch(Cu.reportError);
        }
    };
})();


window.onload = function () {
    try {
        var spacer = document.getElementById("spacer");
        var btn = document.getElementById("help-button");
        spacer.width = btn.boxObject.width;
        if("arguments" in window && window.arguments.length > 0) {
            Editor.init(window.arguments[0].path, window.arguments[0].line);
        }
    } catch(e) {
        Components.utils.reportError(e);
    }
};



function showHTMLTooltip(tip) {
    var ret = false;
    if (/there\.is\.only\.xul$/.test(tip.namespaceURI)) {
        return ret;
    }
    const XLinkNS = "http://www.w3.org/1999/xlink";
    var titleText = null;
    var XLinkTitleText = null;
    while (!titleText && !XLinkTitleText && tip) {
        if (tip.nodeType == Node.ELEMENT_NODE) {
            titleText = tip.getAttribute("title");
            XLinkTitleText = tip.getAttributeNS(XLinkNS, "title");
        }
        tip = tip.parentNode;
    }
    var texts = [titleText, XLinkTitleText];
    var tipNode = document.getElementById("html-tooltip");
    for (var i = 0; i < texts.length; ++i) {
        var t = texts[i];
        if (t && t.search(/\S/) >= 0) {
            tipNode.setAttribute("label", t.replace(/\s+/g, " "));
            ret = true;
        }
    }
    return ret;
}
